/**
 * Copyright(c) 2014 Xunton Solutions
 *
 * History:
 *   15-1-27 下午1:50 Created by dwzhang
 */
package com.jade.modules.cms.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.TransactionAttribute;
import javax.inject.Inject;
import javax.inject.Named;

import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.criterion.Order;
import com.jade.framework.base.criterion.Restrictions;
import com.jade.framework.base.util.PagingList;
import com.jade.framework.base.util.StringUtilsEx;
import com.jade.journal.Journal;
import com.jade.journal.JournalUtils;
import com.jade.modules.cms.*;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用户相关的内容管理接口实现。
 *
 * @author <a href="mailto:dwzhang@xunton.com">dwzhang</a> 
 * @version 1.0 15-1-27 下午1:50
 */
//@Named ("module_userContentManager")
public class UserContentManagerImpl implements UserContentManager
{
    private ContentCountManager countManager;
    private UserContentDao userContentDao;
    Journal journal = JournalUtils.getJournal(ContentBrowserRecord.NAME);

    @Inject
    public void setUserContentDao(@Named ("module_cmsUserContentDao") UserContentDao userContentDao)
    {
        this.userContentDao = userContentDao;
    }

    @Inject
    public void setCountManager(@Named ("module_cmsCountManager") ContentCountManager countManager)
    {
        this.countManager = countManager;
    }


    public void addBrowserRecord(ContentBrowserRecord browserRecord)
            throws CmsException
    {
        browserRecord.setBrowserDate(new Date());
        if (StringUtilsEx.isNotBlank(browserRecord.getUserAgent())) {
            browserRecord.setUserAgent(StringUtilsEx.abbreviate(browserRecord.getUserAgent(), 250));
        }
        journal.infoEntity(browserRecord);
        countManager.addCount(CmsUserEntity.ETYPE_CONTENT, browserRecord.getContentId(), ContentCount.TYPE_BROWSER, 1);
    }

    public Map<Long, Long> getBrowserCount(long... contentIds)
    {
        Map<Long, Long> countMap = new HashMap<Long, Long>();
        for (long contentId : contentIds) {
            countMap.put(contentId, getBrowserCount(contentId));
        }
        return countMap;
    }

    public long getBrowserCount(long contentId)
    {
        return countManager.getCount(CmsUserEntity.ETYPE_CONTENT, contentId, ContentCount.TYPE_BROWSER);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void addComment(Comment comment)
            throws CmsException
    {
        comment.setCreationDate(new Date());
        userContentDao.addComment(comment);
        countManager.addCount(comment.getEntityType(), comment.getEntityId(), ContentCount.TYPE_COMMENT, 1);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void filterComment(long... ids)
            throws CmsException
    {
        for (long id : ids) {
            Comment comment = getComment(id);
            if (comment != null) {
                comment.setStatus(Comment.STATUS_FILTERED);
                userContentDao.updateComment(comment);
            }
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeComment(long... ids)
            throws CmsException
    {
        for (long id : ids) {
            Comment comment = getComment(id);
            if (comment != null) {
                userContentDao.removeComment(comment);
                countManager.addCount(comment.getEntityType(), comment.getEntityId(), ContentCount.TYPE_COMMENT, -1);
            }
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeAllComment(long contentId)
            throws CmsException
    {
        int count = userContentDao.removeComment(contentId);
        //更新数量
        countManager.addCount(Comment.ETYPE_CONTENT, contentId, ContentCount.TYPE_COMMENT, -count);
    }

    public Comment getComment(long id)
    {
        return userContentDao.getComment(id);
    }

    public Map<Long, Long> getCommentCounts(long... contentIds)
    {
        Map<Long, Long> countMap = new HashMap<Long, Long>();
        for (long contentId : contentIds) {
            countMap.put(contentId, getCommentCount(contentId));
        }
        return countMap;
    }

    public long getCommentCount(long contentId)
    {
        return countManager.getCount(CmsUserEntity.ETYPE_CONTENT, contentId, ContentCount.TYPE_COMMENT);
    }

    public PagingList<Comment> queryComment(long contentId, int offset, int length)
    {
        Criteria criteria = new Criteria(offset, length);
        criteria.addOrder(Order.desc("creationDate"));
        return userContentDao.queryComment(contentId, criteria);
    }

    public PagingList<Comment> queryComment(Criteria criteria)
    {
        return userContentDao.queryComment(criteria);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void addFavorite(Favorite favorite)
            throws CmsException
    {
        if (isFavorite(favorite.getUserType(), favorite.getUserId(), favorite.getEntityType(), favorite.getEntityId())) {
            return;
        }

        favorite.setCreationDate(new Date());
        userContentDao.addFavorite(favorite);
        countManager.addCount(favorite.getEntityType(), favorite.getEntityId(), ContentCount.TYPE_FAVORITE, 1);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeFavorite(long... ids)
            throws CmsException
    {
        for (long id : ids) {
            Favorite favorite = getFavorite(id);
            if (favorite != null) {
                userContentDao.removeFavorite(favorite);
                countManager.addCount(favorite.getEntityType(), favorite.getEntityId(), ContentCount.TYPE_FAVORITE, -1);
            }
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeFavorite(String userType, String userId, String entityType, long entityId)
            throws CmsException
    {
        int c = userContentDao.removeFavorite(userType, userId, entityType, entityId);
        countManager.addCount(entityType, entityId, ContentCount.TYPE_FAVORITE, -c);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeFavorite(String userType, String userId)
            throws CmsException
    {
        List<Favorite> favorites = queryFavorite(userType, userId, 0, Integer.MAX_VALUE);
        for (Favorite favorite : favorites) {
            userContentDao.removeFavorite(favorite);
            countManager.addCount(favorite.getEntityType(), favorite.getEntityId(), ContentCount.TYPE_FAVORITE, -1);
        }
    }

    public Favorite getFavorite(long id)
    {
        return userContentDao.getFavorite(id);
    }

    public boolean isFavorite(String userType, String userId, String entityType, long entityId)
    {
        Criteria criteria = new Criteria(0, 1);
        criteria.add(Restrictions.eq("userType", userType));
        criteria.add(Restrictions.eq("userId", userId));
        criteria.add(Restrictions.eq("entityType", entityType));
        criteria.add(Restrictions.eq("entityId", entityId));
        List<Favorite> favorites = queryFavorite(criteria);
        if (favorites.isEmpty()) {
            return false;
        }
        else {
            return true;
        }
    }

    public Map<Long, Long> getFavoriteCount(String etype, long... eids)
    {
        Map<Long, Long> countMap = new HashMap<Long, Long>();
        for (long eid : eids) {
            countMap.put(eid, getFavoriteCount(etype, eid));
        }
        return countMap;
    }

    public long getFavoriteCount(String etype, long eid)
    {
        return countManager.getCount(etype, eid, ContentCount.TYPE_FAVORITE);
    }

    public PagingList<Favorite> queryFavorite(String ownerType, String ownerId, int offset, int length)
    {
        Criteria criteria = new Criteria(offset, length);
        criteria.add(Restrictions.eq("userType", ownerType));
        criteria.add(Restrictions.eq("userId", ownerId));
        criteria.addOrder(Order.desc("creationDate"));
        return queryFavorite(criteria);
    }

    public PagingList<Favorite> queryFavorite(Criteria criteria)
    {
        return userContentDao.queryFavorite(criteria);
    }
}
